Думаю, все помнят о бодром способе склейки словарей и распаковки списков:
>>> {'x': 1, **{'y': 2}}
{'x': 1, 'y': 2}
>>> print(*[1, [], 3])
1 [] 3
А я сегодня случайно наткнулся на чудесный PEP-3132. Он повествует о нетрадиционном применении оператора распаковки итераторов *
.
>>> xs = [1, 2, 3, 4, 5]
>>> head, *rest = xs
>>> head
1
>>> rest
[2, 3, 4, 5]
>>> xs = [1, 2, 3, 4, 5]
>>> *rest, last = xs
>>> last
5
>>> rest
[1, 2, 3, 4]
Никто не запрещает взять голову и хвост списка одновременно:
>>> xs = [1, 2, 3, 4, 5]
>>> head, *rest, last = xs
>>> head
1
>>> rest
[2, 3, 4]
>>> last
5
Если *rest
не нужен -- можно совершенно спокойно заменить его на *_
. Хотя мне такое уже не нравится, какой-то perl выходит. :)
И даже вот так можно:
>>> xs = [1, 2, 3, 4, 5, 6]
>>> first, second, *rest, pre_last, last = xs
>>> first
1
>>> second
2
>>> rest
[3, 4]
>>> pre_last
5
>>> last
6
Единственная проблема в том, что нужно быть 100% уверенным в содержимом списка: сколько в нём элементов и какие элементы где возможны.
В случае, когда количество распаковываемых элементов совпадает с длиной распаковываемого списка, в *rest
приедет пустой список. Отличить это поведение от штатной обработки списка типа [1, [], 2]
невозможно:
>>> xs = [1, 2]
>>> first, *rest, last = xs
>>> first
1
>>> last
2
>>> rest
[]
В случае, когда список короче желаемого, разумеется, будет вылетать исключение:
>>> xs = [1, 2]
>>> a, *b, c, d = xs
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected at least 3, got 2)
Такая вот красота. По-моему, такой способ записи в некоторых случаях может выглядеть намного нагляднее стандартного
питоньего xs[0]
для головы списка, xs[1:]
для хвоста и так далее.